

///////////////////////////////////////////////////////
/*

*/
///////////////////////////////////////////////////////


//#include "Param.h"
//#include "cct_make_js.h"
#include   "stdio.h"
#include   "string.h"
#include  "iotv30_config.h"
#include  "uart_printf.h"

//#include "tcp.h"

#include "user_flash.h"    
#include <stdlib.h>



 volatile uint8_t  gucPowerDownIntFlag ;

uint8_t   ucUserDataSaveFlag   = 0;  
uint8_t   ucUpdateDataSaveFlag = 0;  


uint8_t gucCCT_ID[CCT_ID_LEN]={0x01,0x00,0x00,0x00,0x03,0x80 }; // 010000000380 ----九联装机


  UpdateData_u  UpdateData;

   
  UserData_u    UserData;


//EthString_st    EthString;


static void User_DefaultSet(void)
{				
    memset(&UserData.Buffer[0],0, USER_DATA_BUF_MAX );

    UserData.Reg.First = FLASH_UPDATE_FIRST_WR ;	


	UserData.Reg.EthParam.local_ip[0]   = 192;
	UserData.Reg.EthParam.local_ip[1]   = 168;
	UserData.Reg.EthParam.local_ip[2]   = 1;
	UserData.Reg.EthParam.local_ip[3]   = 88;

	UserData.Reg.EthParam.gateway[0]   = 192;
	UserData.Reg.EthParam.gateway[1]   = 168;
	UserData.Reg.EthParam.gateway[2]   = 1;
	UserData.Reg.EthParam.gateway[3]   = 1;

	UserData.Reg.EthParam.subnet[0]   = 255;
	UserData.Reg.EthParam.subnet[1]   = 255;
	UserData.Reg.EthParam.subnet[2]   = 255;
	UserData.Reg.EthParam.subnet[3]   = 0;

	UserData.Reg.EthParam.local_port   = 5000;

	UserData.Reg.EthParam.dns_server[0]   = 114;
	UserData.Reg.EthParam.dns_server[1]   = 114;
	UserData.Reg.EthParam.dns_server[2]   = 114;
	UserData.Reg.EthParam.dns_server[3]   = 114;


//----需要放在------Param_Init( )--之后-----------------
	UserData.Reg.EthParam.local_mac[0]   = 0x02;
	UserData.Reg.EthParam.local_mac[1]   = 0xDC;
	UserData.Reg.EthParam.local_mac[2]   = gucCCT_ID[2];
	UserData.Reg.EthParam.local_mac[3]   = gucCCT_ID[3];
	UserData.Reg.EthParam.local_mac[4]   = gucCCT_ID[4];
	UserData.Reg.EthParam.local_mac[5]   = gucCCT_ID[5];


	 UserData_SaveEnable( ); //开机即保存，防止看门狗复位	
}




void File_Create(const char *file_name)
{	
 FILE * pFile = NULL;

  //打开文件
 
     pFile = fopen (file_name,"rb");//以（只读）形式打开文件 
    logout( "fopen %s\n",file_name );

  //文件操作
	if (  NULL == pFile)
	{// //打开失败---文件不存在
          pFile = fopen (file_name,"wb");//以（只写）形式打开文件----文件不存在则创建文件----如果存在则覆盖原来的文件-------

		if (  NULL == pFile)
		{// //创建文件失败----路径不存在
           UartPrintString( "File_Create() fail \n" );

		}else{

           UartPrintString( "File_Create() ok \n" );
           fclose(pFile); 	
		}

	}else{

       logout( "%s already Create() \n",file_name );
       fclose(pFile);
	}


  pFile = NULL;

}





/////-------与 UserFlash_Init( )--打开文件形势不一样------------
//以（只读）形式打开文件 
void UserFlash_Create(void)
{	

 File_Create(USER_FLASH_FILE_PATH);

}





//以（读写）形式打开文件 
void UserFlash_Init(void)
{	

  FILE * pFile = NULL;


  logout( "%s\n",__FUNCTION__ );

 //  memset(&UpdateData.Buffer[0],0, UPDATE_DATA_BUF_MAX );

    memset(&UserData.Buffer[0],0, USER_DATA_BUF_MAX );

  //打开文件
   //pFile = fopen ("./user_flash.txt","r+b");//以（读写）形式打开文件    
  // pFile = fopen (USER_FLASH_FILE_PATH,"r+b");//以（读写）形式打开文件 
     pFile = FLASH_Unlock( ) ;

  //文件操作
	if (  NULL == pFile)
	{// //打开失败---文件不存在

	    UartPrintString( "fopen ");
		UartPrintString( USER_FLASH_FILE_PATH);
		UartPrintString( "fail\n" );

/*	
          pFile = fopen ("./user_flash.txt","wb");//以（只写）形式打开文件----文件不存在则创建文件----如果存在则覆盖原来的文件-------

           User_DefaultSet( );

           WriteDataToFlash_8Bits(pFile, &UpdateData.Buffer[0],FLASH_UPDATE_DATA_PAGE,UPDATE_DATA_BUF_MAX); 

		   fclose(pFile);

           UartPrintString( "creat user flash \n" );
*/
	}else{

		//	ReadDataFromFlash_8Bits(pFile, &UpdateData.Buffer[0],FLASH_UPDATE_DATA_PAGE,UPDATE_DATA_BUF_MAX);  //读取远程升级数据	
		//	if( FLASH_UPDATE_FIRST_WR != UpdateData.Reg.First )		

			ReadDataFromFlash_8Bits(pFile, &UserData.Buffer[0],FLASH_USER_DATA_PAGE,USER_DATA_BUF_MAX);  

			if( FLASH_USER_FIRST_WR != UserData.Reg.First )  // debug 2023-12-30 FLASH_UPDATE_FIRST_WR
			{//第一次上电
                User_DefaultSet( );
				
			}
	
	
      FLASH_Lock( pFile);

	}
			
    EthParam_Update( );
    Read_EthParam( );

}



void Read_EthParam(void)
{

  EthParam_st*   peth_param =NULL;
  peth_param = &UserData.Reg.EthParam;

#if   TESTING_ON_PCENABLE    //在PC环境下测试---

const char *eth_name = "ens33";   //pc 
#else 
const char *eth_name = "eth0";  //f133

#endif

#if 0
    get_local_mac(eth_name, EthString.local_mac);
    printf("local %s mac: %s\n", eth_name, EthString.local_mac);

    get_local_ip(eth_name, EthString.local_ip);
    printf("local %s ip: %s\n", eth_name, EthString.local_ip);

#endif




#if 0


     //----------------目前菜单还没有显示mac---需要考虑增加------------------------ 
	memset(EthString.local_mac,0,sizeof(EthString.local_mac) );
    get_local_mac(eth_name, EthString.local_mac,peth_param->local_mac);
    printf("local %s mac: %s\n", eth_name, EthString.local_mac);

	memset(EthString.local_ip,0,sizeof(EthString.local_ip) );
    get_local_ip(eth_name, EthString.local_ip,peth_param->local_ip);
    printf("local %s ip: %s\n", eth_name, EthString.local_ip);

    memset(EthString.gateway,0,sizeof(EthString.gateway) );
	
    sprintf( EthString.gateway , "%d.%d.%d.1", peth_param->local_ip[3],peth_param->local_ip[2],peth_param->local_ip[1]);//小端
 //   sprintf( EthString.gateway , "%d.%d.%d.1", peth_param->local_ip[0],peth_param->local_ip[1],peth_param->local_ip[2]);  //大端


    CCT_Config_Save_To_js( );


#endif


}






void EthParam_Update(void)
{	
#if 0	

  EthParam_st*   peth_param =NULL;
  peth_param = &UserData.Reg.EthParam;

	memset(EthString.local_ip,0,sizeof(EthString.local_ip) );
    sprintf(EthString.local_ip,"%d.%d.%d.%d.",peth_param->local_ip[0], peth_param->local_ip[1],peth_param->local_ip[2],peth_param->local_ip[3] );

	memset(EthString.gateway,0,sizeof(EthString.gateway) );
    sprintf(EthString.gateway,"%d.%d.%d.%d.",peth_param->gateway[0], peth_param->gateway[1],peth_param->gateway[2],peth_param->gateway[3] );

	memset(EthString.subnet,0,sizeof(EthString.subnet) );
    sprintf(EthString.subnet,"%d.%d.%d.%d.",peth_param->subnet[0], peth_param->subnet[1],peth_param->subnet[2],peth_param->subnet[3] );


	memset(EthString.local_mac,0,sizeof(EthString.local_mac) );
    sprintf(EthString.local_mac,"%d:%d:%d:%d:%d:%d",peth_param->local_mac[0], peth_param->local_mac[1],peth_param->local_mac[2],peth_param->local_mac[3] ,peth_param->local_mac[4],peth_param->local_mac[5]);


	memset(EthString.port,0,sizeof(EthString.port) );
    sprintf(EthString.port,"%d",peth_param->local_port );
#endif

}






//以（读写）形式打开文件  
FILE*  FLASH_Unlock(void)
{	
   return fopen (USER_FLASH_FILE_PATH,"r+b");//以（读写）形式打开文件      
}


void  FLASH_Lock(FILE* pFile)
{	
	//文件操作
	if (  NULL != pFile)
	{//
        fflush(pFile);//刷新缓冲区时，才将输出缓冲区的数据写到文件（磁盘）	
		fclose(pFile); //注：fclose在关闭文件的时候，也会刷新缓冲区	
		pFile = NULL;

	}else{ //打开失败---文件不存在

		UartPrintString( "FLASH_Lock() fclose fail!\n" );
	}

}



/**
 *  @brief //以（读写）形式打开文件  
 *  @param [in] file_name----文件名---不包括路径----//文件名不能超过100Bs---路径名最大155Bs
 *  @param [out] null
 *
 *  @return FILE*
 *   != NULL -- 打开文件成功
 *   = NULL -- 打开文件失败
 */

FILE*  File_Unlock(const char *file_name)
{	
char str_buf[255]=CCT_APP_INSTALL_PATH;

 FILE * pFile = NULL;

    if( NULL==file_name)
    {
      return  NULL;
    }

    if( strlen(file_name) >100)
    {//文件名不能太长---路径名最大155
      return  NULL;
    }


    memset(str_buf,0,sizeof(char) );
    memcpy(str_buf, CCT_APP_INSTALL_PATH, sizeof(CCT_APP_INSTALL_PATH) );
	strcat(str_buf,file_name);

   logout("open file %s\n",str_buf);

    pFile = fopen (str_buf,"r+b");     

    if(NULL== pFile)
	{
       File_Create(str_buf);
	}

    return pFile = fopen (str_buf,"r+b");  

}












/////-------判断文件是否存在-----------

/**
 *  @brief 判断文件是否存在--
 *  @param [in] file_name----文件名---不包括路径----
 *  @param [out] null
 *
 *  @return
 *   = true -- 文件存在
 *   = false - 文件不存在
 */

bool  File_Test(const char *file_name)
{	
 FILE * pFile = NULL;

//char str_buf[255]=CCT_APP_INSTALL_PATH;
char str_buf[255];

    if( NULL==file_name)
    {
      return  false;
    }

    if( strlen(file_name) >100)
    {//文件名不能太长---路径名最大155
      return  false;
    }


    memset(str_buf,0,sizeof(char) );
    memcpy(str_buf, CCT_APP_INSTALL_PATH, sizeof(CCT_APP_INSTALL_PATH) );
	strcat(str_buf,file_name);
   
     pFile = fopen (str_buf,"rb");

    logout( "fopen %s\n",str_buf );

  //文件操作
	if ( NULL == pFile)
	{// //打开失败---文件不存在

        logout( "%s not exist\n",str_buf );
        UartPrintString( str_buf );		
        UartPrintString( "file not exist\n" );
        return false;

	}else{

        logout( "%s exist\n",str_buf );
        UartPrintString( str_buf );		
        UartPrintString( "file exist\n" );

       fclose(pFile);
	   pFile = NULL;

       return true;	   
	}


}






void UserFlash_SaveProcess(void)
{

  FILE * pFile=NULL;

	if( 0!= gucPowerDownIntFlag )
	{// 在外部打印--有多余的时间才打印
	   gucPowerDownIntFlag = 0;	
	
	}
	

	
	if( 0 != ucUserDataSaveFlag )
	{		

       LOG_NAME();
		 //打开文件
		//pFile = fopen (USER_FLASH_FILE_PATH,"r+b");//以（读写）形式打开文件    USER_FLASH_FILE  
        pFile = FLASH_Unlock(); 


	   //文件操作
		if (  NULL != pFile)
		{//

		    WriteDataToFlash_8Bits( pFile,&UserData.Buffer[0],FLASH_USER_DATA_PAGE,USER_DATA_BUF_MAX); 		
            ucUserDataSaveFlag = 0;

            FLASH_Lock(pFile); 

			//fclose(pFile); //注：fclose在关闭文件的时候，也会刷新缓冲区	
			//pFile = NULL;

		}else{ //打开失败---文件不存在

	        ucUserDataSaveFlag = 0;
            UartPrintString( "save user flash fail!\n" );

		}
	
	}


	if( 0 != ucUpdateDataSaveFlag )
	{			
		 //打开文件
		//pFile = fopen (USER_FLASH_FILE_PATH,"r+b");//以（读写）形式打开文件    USER_FLASH_FILE  
          pFile = FLASH_Unlock(); 
           LOG_NAME();
	   //文件操作
		if (  NULL != pFile)
		{//

		    WriteDataToFlash_8Bits( pFile,&UpdateData.Buffer[0],FLASH_UPDATE_DATA_PAGE,UPDATE_DATA_BUF_MAX); 	

            FLASH_Lock(pFile); 

			//fclose(pFile); //注：fclose在关闭文件的时候，也会刷新缓冲区	
			//pFile = NULL;

		}else{ //打开失败---文件不存在

            UartPrintString( "save UpdateData flash fail!\n" );
		}


          EthParam_Update( );

	      ucUpdateDataSaveFlag = 0;

    }

		
}



   ////-------ver.4.30------------------------
void ResetUpdateFlag(void)
{			
	UpdateData.Reg.StartFlag = 0;
	UpdateData.Reg.DoneFlag  = 0;		
	UpdateData.Reg.Cnt       = 0;	

   system("rm CCT_APP_UPGRADE_OK_FILE_PATH"); //绝对路径

}

   ////-------ver.4.30------------------------
void SetUpdateFlag(void)
{
	UpdateData.Reg.StartFlag = 0;
	UpdateData.Reg.DoneFlag  = 1;		
	UpdateData.Reg.Cnt       = 0;	
	
    UpdateData_SaveEnable( );

    system("touch CCT_APP_UPGRADE_OK_FILE_PATH");
}


void UserData_SaveEnable(void)
{
    ucUserDataSaveFlag = 1;
}


void UpdateData_SaveEnable(void)
{
    ucUpdateDataSaveFlag = 1;
}



 
//	fseek(fp,dst_flash_addr,SEEK_SET );  //SEEK_SET---绝对定位， SEEK_CUR, SEEK_END  
// 函数原型：int fseek(FILE *stream,long offset,int framewhere)
// 作用：重定位文件内部的指针
// 参数：第一个为文件指针，第二个是指针的偏移量，第三个是指针偏移起始位置
// 返回值：重定位成功返回0，否则返回非零值
// 第一个参数 stream 为文件指针
// 第二个参数 offset 为偏移量，整数表示正向偏移，负数表示负向偏移
// 第三个参数 whence 设定从文件的哪里开始偏移,可以使用3个常量之一,可能取值为：SEEK_CUR、 SEEK_END 或 SEEK_SET
// SEEK_SET  -  文件开头// SEEK_CUR  -  当前位置  // SEEK_END  -  文件结尾



//size_t fwrite ( void *buffer, size_t size, size_t count, FILE *stream) ;
//buffer  用于接收数据的内存地址
///size   要读写的字节数，单位是字节
//count  要进行读写多少个size字节的数据项,每个元素是size字节


//size_t fread ( void *buffer, size_t size, size_t count, FILE *stream) ;
//buffer  用于接收数据的内存地址
///size   要读写的字节数，单位是字节
//count  要进行读写多少个size字节的数据项,每个元素是size字节




//返回值0--表示读flash失败，非0表示成功---
uint8_t ReadDataFromFlash_8Bits(FILE *fp, uint8_t *data, uint32_t flash_addr, uint16_t len)
{
	
	if( NULL == fp )
	{
		return 0;
	}

	fseek(fp,flash_addr,SEEK_SET );  //SEEK_SET---绝对定位， SEEK_CUR, SEEK_END 

    if( fread (data,1,len,fp) <0 )//读文件数据
	{
       UartPrintString( " ReadDataFromFlash_8Bits() fail" );
	   //printf("");

       return 0;	//读出错
	}else{

       return 1;	
	}

	
}





//返回值0--表示写flash失败，非0表示成功-------内部包含页擦除功能----
uint8_t WriteDataToFlash_8Bits( FILE *fp, uint8_t* data,uint32_t dst_flash_addr,uint16_t data_len)
{	

	if( NULL == fp )
	{
		return 0;
	}

     LOG_NAME();

	fseek(fp,dst_flash_addr,SEEK_SET );  //SEEK_SET---绝对定位， SEEK_CUR, SEEK_END 

    if( fwrite (data,1,data_len,fp) <0 )//写文件数据
	{
       UartPrintString( " WriteDataToFlash_8Bits() fail" );
	   //printf("");

       return 0;	//读出错
	}else{

       return 1;	
	}

	
}




//返回值0--表示写flash失败，1表示成功--------需要在外部先擦除，才能调用该函数------
//使用之前需要 先擦除和使能 FLASH_Unlock( )
uint8_t  ProgramDataToFlash_8Bits( FILE *fp, uint8_t* data,uint32_t dst_flash_addr,uint16_t data_len)
{	

	if( NULL == fp )
	{
		return 0;
	}


	fseek(fp,dst_flash_addr,SEEK_SET );  //SEEK_SET---绝对定位， SEEK_CUR, SEEK_END 

    if( fwrite (data,1,data_len,fp) <0 )//读文件数据
	{
       UartPrintString( " ReadDataFromFlash_8Bits() fail" );
	   //printf("");

       return 0;	//读出错
	}else{

       return 1;	
	}





#if 0

	enRet = EFM_WriteFlash(dst_flash_addr, data,data_len);
		
	if(  Ok  == enRet )  
	{
		// FLASH_Lock( );
	   return 1;
	}else{
			printf("WriteFlash err %d\r\n", enRet);
		
		// FLASH_Lock( );
	   return 0;
	}

#endif


	
}




//返回值0--表示写flash失败，非0表示成功-------内部包含页擦除功能----

uint8_t Flash_EraseSector(FILE* pFile, uint32_t u32Addr)
{

uint8_t  buf_zero[FLASH_SECTOR_SIZE]={0};


    if (u32Addr >= (FLASH_BASE + FLASH_SIZE))
    {

#if  ( DEBUG_PRINT_ENABLE || DEBUG_MIN_PRINT_ENABLE   )  
       printf( "error: u32Addr >= FLASH_BASE + FLASH_SIZE \n" );
#endif

        return 0;//4194304
    }

    if (0UL != (u32Addr % 4U))
    {
        u32Addr = (u32Addr / FLASH_SECTOR_SIZE) * FLASH_SECTOR_SIZE;
    }

   
		//打开文件
	//	pFile = fopen (USER_FLASH_FILE_PATH,"r+b");//以（读写）形式打开文件    USER_FLASH_FILE  

	//文件操作
		if (  NULL != pFile)
		{//

            memset(&buf_zero[0],0,FLASH_SECTOR_SIZE);

#if  ( DEBUG_PRINT_ENABLE || DEBUG_MIN_PRINT_ENABLE   )  
             printf("Flash_Erase... PAGE=%x\n",u32Addr );
	        // printf("Flash_EraseSector pFile=%p,PAGE=%x\n",pFile,u32Addr);
#endif

			if( 0 == WriteDataToFlash_8Bits( pFile,&buf_zero[0],u32Addr, FLASH_SECTOR_SIZE ) 	)
			{
				UartPrintString( "Flash_EraseSector fail\n" );

			}else{

				UartPrintString( "Flash_EraseSector ok\n" );
			}


			//fclose(pFile); //注：fclose在关闭文件的时候，也会刷新缓冲区	
			//pFile = NULL;

		}else{ //打开失败---文件不存在

			UartPrintString( "Flash_EraseSector open fail!\n" );
			return 0;
		}
	


return 1;


}



#if 0
uint8_t FLASH_ErasePage(FILE* pFile,uint32_t Page_Address)
{

return Flash_EraseSector( pFile,  Page_Address);

}

#endif






                
 unsigned char FlashWriteCheck(FILE *fp, unsigned long ulFlashAdr)
{
    unsigned char ucReturnValue = 0 ,ucTemp[2];
    uint16_t uiTemp;

    ReadDataFromFlash_8Bits(fp,&ucTemp[0], ulFlashAdr,2);

    uiTemp = ucTemp[1]; 
    uiTemp = (uiTemp<<8) | ucTemp[0]; 
    
    if (uiTemp == FLASH_VALID_FLAG1 || uiTemp == FLASH_VALID_FLAG2){   
        ucReturnValue = 1;
    }else{
        ucReturnValue = 0;
    }
    
    return(ucReturnValue);
}





//返回值0--表示写flash失败，非0表示成功-------内部包含页擦除功能----
uint8_t WriteDataToFlash_16Bits( FILE *fp, uint16_t* data,uint32_t dst_flash_addr,uint16_t data_len)
{	

	if( NULL == fp )
	{
		return 0;
	}


	fseek(fp,dst_flash_addr,SEEK_SET );  //SEEK_SET---绝对定位， SEEK_CUR, SEEK_END 

    if( fwrite (data,2,data_len,fp) <0 )//读文件数据
	{
       UartPrintString( " WriteDataToFlash_16Bits() fail" );
	   //printf("");

       return 0;	//读出错
	}else{

       return 1;	
	}

	
}


//返回值0--表示写flash失败，非0表示成功-------内部包含页擦除功能----
uint8_t WriteDataToFlash_32Bits( FILE *fp, uint32_t* data,uint32_t dst_flash_addr,uint16_t data_len)
{	

	if( NULL == fp )
	{
		return 0;
	}


	fseek(fp,dst_flash_addr,SEEK_SET );  //SEEK_SET---绝对定位， SEEK_CUR, SEEK_END 

    if( fwrite (data,4,data_len,fp) <0 )//读文件数据
	{
       UartPrintString( " WriteDataToFlash_32Bits() fail" );
	   //printf("");

       return 0;	//读出错
	}else{

       return 1;	
	}

}



void WriteHalfWordToFlash(FILE *fp, uint16_t  uiWord, unsigned long ulFlashAdr)
{
    WriteDataToFlash_16Bits(fp,&uiWord, ulFlashAdr, 1);
}

void WriteWordToFlash(FILE *fp, uint32_t  uWord, unsigned long ulFlashAdr)
{
    WriteDataToFlash_32Bits(fp,&uWord, ulFlashAdr, 1);
}




 
 
 
 uint32_t  Flash_GetAppSize(void)
 {
   return  APP_Flash_Size;
 }  

